package com.yunchang.springboot.scheduled.mwsfinance;


import com.yunchang.springboot.base.BaseService;
import com.yunchang.springboot.mapper.caravan.CaravanMskuDataMapper;
import com.yunchang.springboot.mapper.finance.FinanceCaravanDebitCreditRelationMapper;
import com.yunchang.springboot.mapper.mws.finances.MwsFinancesFinancialReportMapper;
import com.yunchang.springboot.mapper.mwsfinance.FFbaShipmentSalesMapper;
import com.yunchang.springboot.mapper.mwsfinance.FInventoryDailyMapper;
import com.yunchang.springboot.mapper.mwsfinance.FPaymentRefundMapper;
import com.yunchang.springboot.mapper.mwsutils.*;
import com.yunchang.springboot.models.mwsfinance.FGoodsInTransit;
import com.yunchang.springboot.models.mwsfinance.FPaymentRefund;
import com.yunchang.springboot.models.mwsfinance.MwsFinancesFinancialReport;
import com.yunchang.springboot.utils.DateUtil;
import com.yunchang.springboot.utils.UUIDUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

/**
 * payment销售退款
 *
 * @author Administrator
 */
@Component
@Configuration
@Service
@Slf4j
@EnableScheduling
public class FPaymentRefundScheduled extends BaseService {

    static final String TRANSACTION_TYPE = "Refund";

    static final String AMOUNT_DESCRIPTION = "Principal";

    static final String FORM = "Payment";

    static final String TYPE = "Otherdefault";

    static final List<String> EU_COUNTRY_LIST = Arrays.asList("DE", "FR", "IT", "UK", "ES");

    private static final String DEBIT_SUBJECT_ID = "140201";

    private static final String CREDIT_SUBJECT_ID = "640107";

    static final String COUNTRY_CODE = "GB";

    static final String COUNTRY_CODE_UK = "UK";

    static String DOCUMENTS_ID = "TKD";

    static String DOCUMENTS_ID_PUSH = "TKRKD";

    /**
     * 出入库明细
     */
    @Autowired
    FInventoryDetailsScheduled fInventoryDetailsScheduled;

    /**
     * finance原始数据
     */
    private MwsFinancesFinancialReportMapper mwsFinancesFinancialReportMapper;

    @Autowired
    public void setMwsFinancesFinancialReportMapper(MwsFinancesFinancialReportMapper mwsFinancesFinancialReportMapper) {
        this.mwsFinancesFinancialReportMapper = mwsFinancesFinancialReportMapper;
    }

    /**
     * 用于查询countryName的类
     */
    private CwfzMarketplaceCountryMapper cwfzMarketplaceCountryMapper;

    @Autowired
    public void setCwfzMarketplaceCountryMapper(CwfzMarketplaceCountryMapper cwfzMarketplaceCountryMapper) {
        this.cwfzMarketplaceCountryMapper = cwfzMarketplaceCountryMapper;
    }

    /**
     * 获取country
     */
    private CwfzCurrencyCountryMapper cwfzCurrencyCountryMapper;

    @Autowired
    public void setCwfzCurrencyCountryMapper(CwfzCurrencyCountryMapper cwfzCurrencyCountryMapper) {
        this.cwfzCurrencyCountryMapper = cwfzCurrencyCountryMapper;
    }

    /**
     * 借贷关系
     */
    private CwfzFinancialSubjectsMapper cwfzFinancialSubjectsMapper;

    @Autowired
    public void setCwfzFinancialSubjectsMapper(CwfzFinancialSubjectsMapper cwfzFinancialSubjectsMapper) {
        this.cwfzFinancialSubjectsMapper = cwfzFinancialSubjectsMapper;
    }

    /**
     * 销售退款财务数据
     */
    private FPaymentRefundMapper fPaymentRefundMapper;

    @Autowired
    public void setFPaymentRefundMapper(FPaymentRefundMapper fPaymentRefundMapper) {
        this.fPaymentRefundMapper = fPaymentRefundMapper;
    }


    /**
     * 用于计算costUnit
     */
    private FFbaShipmentSalesMapper fFbaShipmentSalesMapper;

    @Autowired
    public void setFFbaShipmentSalesMapper(FFbaShipmentSalesMapper fFbaShipmentSalesMapper) {
        this.fFbaShipmentSalesMapper = fFbaShipmentSalesMapper;
    }

    /**
     * 库存数据
     */
    private FInventoryDailyMapper fInventoryDailyMapper;

    @Autowired
    public void setFInventoryDailyMapper(FInventoryDailyMapper fInventoryDailyMapper) {
        this.fInventoryDailyMapper = fInventoryDailyMapper;
    }

    /**
     * 获取stock_sku
     */
    private CaravanMskuDataMapper caravanMskuDataMapper;

    @Autowired
    public void setCaravanMskuDataMapper(CaravanMskuDataMapper caravanMskuDataMapper) {
        this.caravanMskuDataMapper = caravanMskuDataMapper;
    }

    /**
     * 获取costUnit
     */
    private FinanceCaravanDebitCreditRelationMapper financeCaravanDebitCreditRelationMapper;

    @Autowired
    public void setFinanceCaravanDebitCreditRelationMapper(FinanceCaravanDebitCreditRelationMapper financeCaravanDebitCreditRelationMapper) {
        this.financeCaravanDebitCreditRelationMapper = financeCaravanDebitCreditRelationMapper;
    }

    public void getFPaymentRefund(String date) {
        List<MwsFinancesFinancialReport> mwsFinancesFinancialReportList = mwsFinancesFinancialReportMapper.selectByFinanceStatusAndTransactionType(1, TRANSACTION_TYPE,null,date);
        if (null != mwsFinancesFinancialReportList && !mwsFinancesFinancialReportList.isEmpty()) {
            List<Object> fPaymentRefundList = new ArrayList<>(mwsFinancesFinancialReportList.size());
            for (MwsFinancesFinancialReport mwsFinancesFinancialReport : mwsFinancesFinancialReportList) {
                FPaymentRefund fPaymentRefund = new FPaymentRefund();
                fPaymentRefund.setIsManaulAdjust(1);
                fPaymentRefund.setPushStatus(1);
                fPaymentRefund.setDocumentsId(DOCUMENTS_ID + UUIDUtil.getUUID());
                String postedDate = mwsFinancesFinancialReport.getPostedDate();
                fPaymentRefund.setDate(postedDate);
                fPaymentRefund.setPostedDate(postedDate);
                String sellerId = mwsFinancesFinancialReport.getSellerId();
                fPaymentRefund.setSellerId(sellerId);
                String countryCode = mwsFinancesFinancialReport.getCountryCode();
                String currency = mwsFinancesFinancialReport.getCurrency();
                fPaymentRefund.setCurrency(currency);
                String marketplaceName = mwsFinancesFinancialReport.getMarketplaceName();
                countryCode = getCountry(countryCode, currency, marketplaceName);
                if (!StringUtils.isEmpty(countryCode)) {
                    if (countryCode.equals(COUNTRY_CODE)) {
                        countryCode = COUNTRY_CODE_UK;
                    }
                }
                fPaymentRefund.setCountry(countryCode);
                fPaymentRefund.setOrderId(mwsFinancesFinancialReport.getAmazonOrderId());
                fPaymentRefund.setMerchantOrderId(mwsFinancesFinancialReport.getMerchantOrderId());
                fPaymentRefund.setSku(mwsFinancesFinancialReport.getSku());
                String amountDescription = mwsFinancesFinancialReport.getAmountDescription();
                fPaymentRefund.setType(amountDescription);
                Double originalAmount = mwsFinancesFinancialReport.getAmount();
                fPaymentRefund.setOriginalAmount(originalAmount);
                Long quantity = mwsFinancesFinancialReport.getQuantityPurchased();
                fPaymentRefund.setQuantity(Math.toIntExact(quantity));
                if (amountDescription.equals(AMOUNT_DESCRIPTION)) {
                    fPaymentRefund.setWillReturnQuantity(Math.toIntExact(quantity));
                } else {
                    fPaymentRefund.setWillReturnQuantity(0);
                    fPaymentRefund.setPushStatus(3);
                }
                fPaymentRefund.setPriceUnit(new BigDecimal(Math.abs(originalAmount) / quantity).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue());
                fPaymentRefund.setAmount(Math.abs(originalAmount));
                Map<String, String> debitSubjectIdMap = getDebitSubjectId(originalAmount, amountDescription);
                if (null != debitSubjectIdMap && debitSubjectIdMap.containsKey("debitSubjectId2")) {
                    fPaymentRefund.setIsManaulAdjust(2);
                    fPaymentRefund.setDebitSubjectId(debitSubjectIdMap.get("debitSubjectId2"));
                } else {
                    fPaymentRefund.setDebitSubjectId(debitSubjectIdMap.get("debitSubjectId"));
                }
                Map<String, String> creditSubjectIdMap = getCreditSubjectId(originalAmount, amountDescription);
                if (null != creditSubjectIdMap && creditSubjectIdMap.containsKey("creditSubjectId2")) {
                    fPaymentRefund.setIsManaulAdjust(2);
                    fPaymentRefund.setCreditSubjectId(creditSubjectIdMap.get("creditSubjectId2"));
                } else {
                    fPaymentRefund.setCreditSubjectId(creditSubjectIdMap.get("creditSubjectId"));
                }
                fPaymentRefund.setCreateTime(DateUtil.getTodayDate("yyyy-MM-dd HH:mm:ss"));
                fPaymentRefund.setUpdateTime(DateUtil.getTodayDate("yyyy-MM-dd HH:mm:ss"));
                mwsFinancesFinancialReport.setFinanceStatus(2);
                fPaymentRefundList.add(fPaymentRefund);
            }
            try {
                baseInsertList(fPaymentRefundList);
                mwsFinancesFinancialReportMapper.updateMwsFinancesFinancialReportList(mwsFinancesFinancialReportList);
                log.info("payment销售退款对应的财务数据已生成"+date);
            } catch (Exception e) {
                log.error("插入数据是出现错误，payment销售退款" + e);
                throw new RuntimeException("插入数据是出现错误，payment销售退款");
            }
        } else {
            log.info("未查询到对应的payment销售退款数据列表，时间为" + DateUtil.getTodayDate("yyyy-MM-dd HH:mm:ss"));
        }
        getFGoodsInTransit();
    }

    /**
     * 下推数据
     */
    public void getFGoodsInTransit() {
        List<FPaymentRefund> fPaymentRefundList = fPaymentRefundMapper.selectByPushStatusAndWillReturnQuantity(1);
        if (null != fPaymentRefundList && !fPaymentRefundList.isEmpty()) {
            List<Object> fGoodsInTransitList = new ArrayList<>(fPaymentRefundList.size());
            for (FPaymentRefund fPaymentRefund : fPaymentRefundList) {
                FGoodsInTransit fGoodsInTransit = new FGoodsInTransit();
                fGoodsInTransit.setStatus(1);
                fGoodsInTransit.setIsInventoryDetails(1);
                fGoodsInTransit.setDocumentsId(DOCUMENTS_ID_PUSH + UUIDUtil.getUUID());
                fGoodsInTransit.setPostedDate(fPaymentRefund.getPostedDate());
                String sellerId = fPaymentRefund.getSellerId();
                fGoodsInTransit.setSellerId(sellerId);
                String country = fPaymentRefund.getCountry();
                if (EU_COUNTRY_LIST.contains(country)) {
                    country = "EU";
                }
                fGoodsInTransit.setCountry(country);
                String orderId = fPaymentRefund.getOrderId();
                fGoodsInTransit.setOrderId(orderId);
                String merchantOrderId = fPaymentRefund.getMerchantOrderId();
                fGoodsInTransit.setMerchantOrderId(merchantOrderId);
                String sku = fPaymentRefund.getSku();
                fGoodsInTransit.setSku(sku);
                Integer quantity = fPaymentRefund.getQuantity();
                fGoodsInTransit.setQuantity(quantity);
                Double cosyUnit = 60.0;
                Map<String, Double> costUnitMap = getCostUnit(sellerId, sku, orderId, merchantOrderId, country);
                if (null != costUnitMap && costUnitMap.containsKey("costUnit2")) {
                    fGoodsInTransit.setStatus(2);
                    cosyUnit = costUnitMap.get("costUnit2");
                    fGoodsInTransit.setCostUnit(cosyUnit);
                }
                if (null != costUnitMap && costUnitMap.containsKey("costUnit3")) {
                    fGoodsInTransit.setStatus(3);
                    cosyUnit = costUnitMap.get("costUnit3");
                    fGoodsInTransit.setCostUnit(cosyUnit);
                }
                if (null != costUnitMap && costUnitMap.containsKey("costUnit")) {
                    cosyUnit = costUnitMap.get("costUnit");
                    fGoodsInTransit.setCostUnit(cosyUnit);
                }
                fGoodsInTransit.setAmount(new BigDecimal(quantity * cosyUnit).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue());
                fGoodsInTransit.setCurrency("RMB");
                fGoodsInTransit.setDebitSubjectId(DEBIT_SUBJECT_ID);
                fGoodsInTransit.setCreditSubjectId(CREDIT_SUBJECT_ID);
                fGoodsInTransit.setCreateTime(DateUtil.getTodayDate("yyyy-MM-dd HH:mm:ss"));
                fGoodsInTransit.setUpdateTime(DateUtil.getTodayDate("yyyy-MM-dd HH:mm:ss"));
                fPaymentRefund.setPushStatus(2);
                fGoodsInTransitList.add(fGoodsInTransit);
            }
            try {
                baseInsertList(fGoodsInTransitList);
                fPaymentRefundMapper.updateFPaymentRefundList(fPaymentRefundList);
                log.info("payment销售退款的下推数据在途物资财务数据已生成");
            } catch (Exception e) {
                log.error("插入数据是出现错误，payment销售退款下推在途物资数据" + e);
                throw new RuntimeException("插入数据是出现错误，payment销售退款下推在途物资数据");
            }
        } else {
            log.info("未查询到对应的payment销售退款下推在途物资数据数据列表，时间为" + DateUtil.getTodayDate("yyyy-MM-dd HH:mm:ss"));
        }
    }


    /**
     * 获取country
     *
     * @param countryCode
     * @param currency
     * @return
     */
    public String getCountry(String countryCode, String currency, String marketplaceName) {
        String currencyValue = "EUR";
        if (StringUtils.isEmpty(countryCode)) {
            if (currency.equals(currencyValue)) {
                return cwfzMarketplaceCountryMapper.selectCountryByMarketplace(marketplaceName);
            } else {
                return cwfzCurrencyCountryMapper.getCountryPaymentByCurrency(currency);
            }
        } else {
            return countryCode;
        }
    }


    /**
     * 根据originalAmount和type获取debitSubjectId
     *
     * @param originalAmount
     * @param type
     * @return
     */
    public Map<String, String> getDebitSubjectId(Double originalAmount, String type) {
        String debitSubjectId;
        if (null != originalAmount) {
            if (originalAmount > 0) {
                debitSubjectId = cwfzFinancialSubjectsMapper.getDebitSubjectIdPositiveByTypeAndFormTransactionType(type, FORM, TRANSACTION_TYPE);
                if (StringUtils.isEmpty(debitSubjectId)) {
                    type = TYPE;
                    debitSubjectId = cwfzFinancialSubjectsMapper.getDebitSubjectIdPositiveByTypeAndFormTransactionType(type, FORM, TRANSACTION_TYPE);
                    String finalDebitSubjectId1 = debitSubjectId;
                    return new HashMap<String, String>(1) {{
                        put("debitSubjectId2", finalDebitSubjectId1);
                    }};
                } else {
                    String finalDebitSubjectId = debitSubjectId;
                    return new HashMap<String, String>(1) {{
                        put("debitSubjectId", finalDebitSubjectId);
                    }};
                }
            } else if (originalAmount < 0) {
                debitSubjectId = cwfzFinancialSubjectsMapper.getDebitSubjectIdNegativeByTypeAndFormTransactionType(type, FORM, TRANSACTION_TYPE);
                if (StringUtils.isEmpty(debitSubjectId)) {
                    type = TYPE;
                    debitSubjectId = cwfzFinancialSubjectsMapper.getDebitSubjectIdNegativeByTypeAndFormTransactionType(type, FORM, TRANSACTION_TYPE);
                    String finalDebitSubjectId1 = debitSubjectId;
                    return new HashMap<String, String>(1) {{
                        put("debitSubjectId2", finalDebitSubjectId1);
                    }};
                } else {
                    String finalDebitSubjectId = debitSubjectId;
                    return new HashMap<String, String>(1) {{
                        put("debitSubjectId", finalDebitSubjectId);
                    }};
                }
            } else {
                log.warn("根据originalAmount和type获取debitSubjectId,originalAmount等于0,payment其他费用");
            }
        } else {
            log.warn("根据originalAmount和type获取debitSubjectId,originalAmount为空,payment其他费用");
        }
        return null;
    }

    /**
     * 根据originalAmount和type获取creditSubjectId
     *
     * @param originalAmount
     * @param type
     * @return
     */
    public Map<String, String> getCreditSubjectId(Double originalAmount, String type) {
        String creditSubjectId;
        if (null != originalAmount) {
            if (originalAmount > 0) {
                creditSubjectId = cwfzFinancialSubjectsMapper.getCreditSubjectIdPositiveByTypeAndFormTransactionType(type, FORM, TRANSACTION_TYPE);
                if (StringUtils.isEmpty(creditSubjectId)) {
                    type = TYPE;
                    creditSubjectId = cwfzFinancialSubjectsMapper.getCreditSubjectIdPositiveByTypeAndFormTransactionType(type, FORM, TRANSACTION_TYPE);
                    String finalCreditSubjectId = creditSubjectId;
                    return new HashMap<String, String>(1) {{
                        put("creditSubjectId2", finalCreditSubjectId);
                    }};
                } else {
                    String finalCreditSubjectId1 = creditSubjectId;
                    return new HashMap<String, String>(1) {{
                        put("creditSubjectId", finalCreditSubjectId1);
                    }};
                }
            } else if (originalAmount < 0) {
                creditSubjectId = cwfzFinancialSubjectsMapper.getCreditSubjectIdNegativeByTypeAndFormTransactionType(type, FORM, TRANSACTION_TYPE);
                if (StringUtils.isEmpty(creditSubjectId)) {
                    type = TYPE;
                    creditSubjectId = cwfzFinancialSubjectsMapper.getCreditSubjectIdNegativeByTypeAndFormTransactionType(type, FORM, TRANSACTION_TYPE);
                    String finalCreditSubjectId = creditSubjectId;
                    return new HashMap<String, String>(1) {{
                        put("creditSubjectId2", finalCreditSubjectId);
                    }};
                } else {
                    String finalCreditSubjectId1 = creditSubjectId;
                    return new HashMap<String, String>(1) {{
                        put("creditSubjectId", finalCreditSubjectId1);
                    }};
                }
            } else {
                log.warn("根据originalAmount和type获取debitSubjectId,originalAmount为0,payment其他费用");
            }
        } else {
            log.warn("根据originalAmount和type获取debitSubjectId,originalAmount为空,payment其他费用");
        }
        return null;
    }

    /**
     * @param sellerId
     * @param sku
     * @param orderId
     * @param merchantId
     * @param country
     * @return 正常计算得出的costUnit 的key为costUnit，不正常的key值为costUnit2（需将status设置为2）
     */
    public Map<String, Double> getCostUnit(String sellerId, String sku, String orderId, String merchantId, String country) {
        List<String> warehouseList = Arrays.asList("140603", "140605");
        if (!StringUtils.isEmpty(sellerId) && !StringUtils.isEmpty(sku) && !StringUtils.isEmpty(orderId)) {
            Double amount = fFbaShipmentSalesMapper.selectSumAmountBySellerIdAndOrderIdAndSku(sellerId, orderId, sku);
            Integer quantity = fFbaShipmentSalesMapper.selectSumQuantityBySellerIdAndOrderIdAndSku(sellerId, orderId, sku);
            if (null != amount && null != quantity && quantity != 0) {
                return new HashMap<String, Double>(1) {{
                    put("costUnit", new BigDecimal(amount / quantity).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue());
                }};
            }
            Double amountByMerchantId = fFbaShipmentSalesMapper.selectSumAmountBySellerIdAndOrderIdAndSku(sellerId, merchantId, sku);
            Integer quantityByMerchantId = fFbaShipmentSalesMapper.selectSumQuantityBySellerIdAndOrderIdAndSku(sellerId, merchantId, sku);
            if (null != amountByMerchantId && null != quantityByMerchantId && quantityByMerchantId != 0) {
                return new HashMap<String, Double>(1) {{
                    put("costUnit", new BigDecimal(amountByMerchantId / quantityByMerchantId).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue());
                }};
            }
            Map<String, Object> amountAndQuantityMap = fInventoryDailyMapper.selectSumAmountAndSumQuantityBySellerIdAndCountryAndSkuAndWarehouseListAndMinDate(sellerId, country, sku, warehouseList);
            if (null != amountAndQuantityMap && !amountAndQuantityMap.isEmpty()) {
                if(null  != amountAndQuantityMap.get("amount") && null != amountAndQuantityMap.get("quantity")){
                    Double amountByInventory =  new Double(amountAndQuantityMap.get("amount").toString());
                    Integer quantityByInventory = new Integer(amountAndQuantityMap.get("quantity").toString());
                    if (null != amountByInventory && null != quantityByInventory && quantityByInventory != 0) {
                        return new HashMap<String, Double>(1) {{
                            put("costUnit", new BigDecimal(amountByInventory / quantityByInventory).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue());
                        }};
                    }
                }
            }
            String warehouse = "默认仓库";
            String subjectId = "1406";
            String stockSku = getStockSku(sku);
            Map<String, Object> amountAndSkuNumMap = financeCaravanDebitCreditRelationMapper.selectSumSkuNumAndSumAmountByStockSkuAndWarehouseAndSubjectId(stockSku,warehouse,subjectId);
            if(null != amountAndSkuNumMap && null != amountAndSkuNumMap.get("amount") && null != amountAndSkuNumMap.get("skuNum")){
                Double amountByFinance = new Double(amountAndSkuNumMap.get("amount").toString());
                Integer skuNum = new Integer(amountAndSkuNumMap.get("skuNum").toString());
                if (null != amountByFinance && null != skuNum && amountByFinance != 0 && skuNum != 0) {
                    return new HashMap<String, Double>(1) {{
                        put("costUnit3", new BigDecimal((amountByFinance / skuNum)+15).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue());
                    }};
                }
            }
        }
        return new HashMap<String, Double>(1) {{
            put("costUnit2", new BigDecimal(60.0).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue());
        }};
    }

    /**
     * 根据sku获取stockSku
     * @param sku
     * @return
     */
    public String getStockSku(String sku){
        if(StringUtils.isEmpty(sku)){
            log.info("根据sku获取stockSku失败，sku为空，盘库生成财务数据");
            return null;
        }
        return  caravanMskuDataMapper.getStockSku(sku);
    }
}
